package com.inspectortime.webapp.inspector.billing;

import java.text.SimpleDateFormat;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import com.inspectortime.domain.Employee;
import com.inspectortime.domain.InspectorCompany;
import com.inspectortime.domain.billing.Invoice;
import com.inspectortime.domain.billing.Payment;
import com.inspectortime.domain.billing.PaymentMethod;
import com.inspectortime.domain.billing.PaymentSourceType;
import com.inspectortime.repository.Factory;
import com.inspectortime.repository.Repository;
import com.inspectortime.webapp.payment.AuthorizeNetPaymentRequestHelper;
import com.inspectortime.webapp.util.HttpSessionUtils;

public class InitiateInvoicePaymentController extends AbstractController {
	
	private static Log log = LogFactory.getLog(InitiateInvoicePaymentController.class);
	
	private Factory factory;
	private Repository repository;
	private String returnView;
	private boolean authorizeNetTestMode = true;
	
	@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		InspectorCompany inspectorCompany = HttpSessionUtils.retrieveLoggedInCompany(request, repository);
		
		Employee employee = HttpSessionUtils.retrieveLoggedInEmployee(request, repository);

		List<Invoice> invoices = repository.findUnpaidInvoicesForCompanyId((String) inspectorCompany.getId());
		
		ModelAndView mv = new ModelAndView(getReturnView());
		mv.addObject("invoices", invoices);
		
		if (invoices.isEmpty()) {
			return mv;
		}
		
		// Prepare form for a Authorize.net SIM payment submission
		double totalAmount = 0;
		SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
		StringBuilder description = new StringBuilder();
		if (invoices.size() > 1) {
			description.append("Web booking fees for the following dates: ");
			// TODO: Sort invoices by date 
			for (Invoice invoice : invoices) {
				description.append(sdf.format(invoice.getInvoicePeriodStartDate()));
				description.append(" - ");
				description.append(sdf.format(invoice.getInvoicePeriodEndDate()));
				description.append(", ");
				totalAmount += invoice.calculateInvoiceAmount();
			}
			// remove last comma
			if (!invoices.isEmpty()) {
				description.deleteCharAt(description.length()-1);
				description.deleteCharAt(description.length()-1);
				description.append(" ");
			}
		} else {
			description.append("Web booking fees for ");
			description.append(sdf.format(invoices.get(0).getInvoicePeriodStartDate()));
			description.append(" - ");
			description.append(sdf.format(invoices.get(0).getInvoicePeriodEndDate()));
			totalAmount = invoices.get(0).calculateInvoiceAmount();
		}
		
		AuthorizeNetPaymentRequestHelper paymentRequest = new AuthorizeNetPaymentRequestHelper("4LaSp6R8Z", "4rRNxy27zFP65V8y");
		//TODO: Comment out next line
		//totalAmount = 0.01;
		paymentRequest.setAmount(String.valueOf(totalAmount));
		paymentRequest.setDescription(description.toString());
		paymentRequest.generateFingerprint();
		paymentRequest.setTestMode(authorizeNetTestMode);		
		mv.addObject("paymentRequest", paymentRequest);
		mv.addObject("employee", employee);
		
		// Create a payment record in the database which we'll use to look up
		// this transaction during the call-back POST request coming from
		// Authorize.net. Note that incomplete records will probably need to be
		// purged at some point.
		Payment payment = factory.createPayment(PaymentSourceType.INSPECTOR_TIME_INVOICE);
		for (Invoice invoice : invoices) {
			payment.addPaymentLineItem((String) invoice.getId());	
		}		
		payment.setPaymentInvoiceNumber(paymentRequest.getInvoiceNumber());
		payment.setDescription(paymentRequest.getDescription());
		payment.setAmount(totalAmount);
		payment.save();
		
		return mv;
	}
	
	public void setRepository(Repository repository) {
		this.repository = repository;
	}

	public String getReturnView() {
		return returnView;
	}

	public void setReturnView(String returnView) {
		this.returnView = returnView;
	}

	public void setFactory(Factory factory) {
		this.factory = factory;
	}	

	public void setAuthorizeNetTestMode(boolean authorizeNetTestMode) {
		this.authorizeNetTestMode = authorizeNetTestMode;
	}

}
